﻿using System;
using System.Text;
using System.Web;
using Utilities.Log;
using System.IO;
using System.Xml;
using System.Reflection;
namespace Wx.Event
{
    public class Listen
    {
        private static LogHelper log = new LogHelper(typeof(Listen));
        #region
        /// <summary>
        /// 订阅事件
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnSubscribe;
        /// <summary>
        /// 取消订阅
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnUnSubscribe;
        /// <summary>
        /// 扫描二维码
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnScan;
        /// <summary>
        /// 定位
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnLocation;
        /// <summary>
        /// 菜单点击
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnClick;
        /// <summary>
        /// 浏览页面
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnView;

        /// <summary>
        /// 模板信息发送结果通知
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnTemplateSendJobFinish;

        /// <summary>
        /// 接收到文字信息
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnRecvText;
        /// <summary>
        /// 接收到图片信息
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnRecvImage;
        /// <summary>
        /// 接收到语音信息
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnRecvVoice;
        /// <summary>
        /// 接收到视频信息
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnRecvVideo;
        /// <summary>
        /// 接收到短视频信息
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnRecvShortVideo;

        /// <summary>
        /// 接收到连接信息
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnRecvLink;

        /// <summary>
        /// 接收到地址信息
        /// </summary>
        public EventHandler<Wx.Model.Event.Receive> OnRecvLocation;

        #endregion
        public void Receive(HttpContextBase context)
        {
            #region 验证URL
            if (context.Request.Params["echostr"] != null)
            {
                string signature;
                string timestamp;
                string nonce;
                string echostr;
                signature = context.Request.Params["signature"];
                timestamp = context.Request.Params["timestamp"];
                nonce = context.Request.Params["nonce"];
                echostr = context.Request.Params["echostr"];
                log.info("\r\nremoteurl:" + context.Request.UrlReferrer + "\r\nurl:" + context.Request.Url + "\r\nparams:signature = " + signature + " & timestamp = " + timestamp + " & nonce = " + nonce + " & echostr = " + echostr + "\r\n");
                if (Api.Token.ValiDate(signature, timestamp, nonce))
                {
                    log.info("ValiDate Ok!【" + echostr + "】\r\n");
                    context.Response.Clear();
                    context.Response.Write(echostr);
                }
                else
                {
                    log.info("signature:" + signature + ",timestamp:" + timestamp + ",nonce:" + nonce + ",echostr:" + echostr + "\r\nVali Date Error!\r\n");
                    context.Response.Write(string.Empty);
                }
            }
            #endregion
            #region 事件捕获
            else
            {
                log.info("Event" + "\r\n");
                if (context.Request.HttpMethod.ToLower() == "post")
                {
                    string postStr = string.Empty;
                    Stream s = System.Web.HttpContext.Current.Request.InputStream;
                    byte[] b = new byte[s.Length];
                    s.Read(b, 0, (int)s.Length);
                    postStr = Encoding.UTF8.GetString(b);
                    if (!string.IsNullOrEmpty(postStr))
                    {
                        EventRoute(AnalysisEventStr(postStr), context);
                    }
                    else
                    {
                        context.Response.Write("success");
                    }
                }
                else
                {
                    context.Response.Write("success");
                }
            }
            #endregion
        }

        /// <summary>
        /// 分析事件代码
        /// </summary>
        /// <param name="eventStr"></param>
        /// <returns></returns>
        private Wx.Model.Event.Receive AnalysisEventStr(string eventStr)
        {
            log.info("RecvMessage：\r\n" + eventStr + "\r\n"); //计入日志
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(eventStr); //读取XML字符串
            XmlElement rootElement = doc.DocumentElement;
            Wx.Model.Event.Receive recv = new Model.Event.Receive();
            foreach (XmlNode p in rootElement.ChildNodes)
            {
                PropertyInfo o = recv.GetType().GetProperty(p.Name);
                if (o != null)
                    o.SetValue(recv, p.InnerText);
            }
            return recv;
        }

        /// <summary>
        /// 事件路由
        /// </summary>
        /// <param name="param"></param>
        private void EventRoute(Wx.Model.Event.Receive param, HttpContextBase context)
        {
            if (param != null)
            {
                switch (param.MsgType.ToLower())
                {
                    case "text":
                        {
                            if (OnRecvText != null)
                            {
                                OnRecvText(this, param);
                            }
                            else
                            {
                                context.Response.Write("success");
                            }
                            break;
                        }
                    case "image":
                        {
                            if (OnRecvImage != null)
                            {
                                OnRecvImage(this, param);
                            }
                            else
                            {
                                context.Response.Write("success");
                            }
                            break;
                        }
                    case "voice":
                        {
                            if (OnRecvVoice != null)
                            {
                                OnRecvVoice(this, param);
                            }
                            else
                            {
                                context.Response.Write("success");
                            }
                            break;
                        }
                    case "video":
                        {
                            if (OnRecvVideo != null)
                            {
                                OnRecvVideo(this, param);
                            }
                            else
                            {
                                context.Response.Write("success");
                            }
                            break;
                        }
                    case "shortvideo":
                        {
                            if (OnRecvShortVideo != null)
                            {
                                OnRecvShortVideo(this, param);
                            }
                            else
                            {
                                context.Response.Write("success");
                            }
                            break;
                        }
                    case "link":
                        {
                            if (OnRecvLink != null)
                            {
                                OnRecvLink(this, param);
                            }
                            else
                            {
                                context.Response.Write("success");
                            }
                            break;
                        }
                    case "location":
                        {
                            if (OnRecvLocation != null)
                            {
                                OnRecvLocation(this, param);
                            }
                            else
                            {
                                context.Response.Write("success");
                            }
                            break;
                        }
                    case "event":
                        {
                            switch (param.Event.ToLower())
                            {
                                case "subscribe":
                                    {
                                        if (OnSubscribe != null)
                                        {
                                            OnSubscribe(this, param);
                                        }
                                        else
                                        {
                                            context.Response.Write(string.Empty);
                                        }
                                        break;
                                    }
                                case "unsubscribe":
                                    {
                                        if (OnUnSubscribe != null)
                                        {
                                            OnUnSubscribe(this, param);
                                        }
                                        else
                                        {
                                            context.Response.Write(string.Empty);
                                        }
                                        break;
                                    }
                                case "scan":
                                    {
                                        if (OnScan != null)
                                        {
                                            OnScan(this, param);
                                        }
                                        else
                                        {
                                            context.Response.Write(string.Empty);
                                        }
                                        break;
                                    }
                                case "location":
                                    {
                                        if (OnLocation != null)
                                        {
                                            OnLocation(this, param);
                                        }
                                        else
                                        {
                                            context.Response.Write(string.Empty);
                                        }
                                        break;
                                    }
                                case "click":
                                    {
                                        if (OnClick != null)
                                        {
                                            OnClick(this, param);
                                        }
                                        else
                                        {
                                            context.Response.Write(string.Empty);
                                        }
                                        break;
                                    }
                                case "view":
                                    {
                                        if (OnView != null)
                                        {
                                            OnView(this, param);
                                        }
                                        else
                                        {
                                            context.Response.Write(string.Empty);
                                        }
                                        break;
                                    }
                                case "templatesendjobfinish":
                                    {
                                        if (OnTemplateSendJobFinish != null)
                                        {
                                            OnView(this, param);
                                        }
                                        else
                                        {
                                            context.Response.Write(string.Empty);
                                        }
                                        break;
                                    }
                                default:
                                    {
                                        context.Response.Write(string.Empty);
                                        break;
                                    }
                            }
                            break;
                        }
                    default:
                        {
                            context.Response.Write(string.Empty);
                            break;
                        }
                }
            }
            else
            {
                context.Response.Write(string.Empty);
            }
        }
    }
}




